package com.sihai.ehr.service.impl;

import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.Resource;

import com.sihai.ehr.jdbc.MemberService;
import com.sihai.ehr.jdbc.QingJia;
import com.sihai.ehr.jdbc.QingJiaService;
import com.sihai.ehr.model.biz.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.sihai.core.DataAccessor;
import com.sihai.core.Limit;
import com.sihai.core.LimitedList;
import com.sihai.ehr.model.sys.AuditStatus;
import com.sihai.ehr.model.sys.EmployeeinfoTypeEnum;
import com.sihai.ehr.model.sys.Organization;
import com.sihai.ehr.model.sys.OrganizationAuditing;
import com.sihai.ehr.repository.AuditingRepository;
import com.sihai.ehr.repository.EmployeeinfoLogRepository;
import com.sihai.ehr.repository.TrainPlanRepository;
import com.sihai.ehr.service.AuditBaseService;

/**
 * @author: wxn
 * @since: 12-7-15 下午13:53
 */
@Service("auditBaseService")
public class AuditBaseServiceImpl implements AuditBaseService {
	@Resource
	private DataAccessor dataAccessor;

	@Resource
	private AuditingRepository auditingRepository;

	@Resource
	private TrainPlanRepository trainPlanRepository;

	@Resource
	private EmployeeinfoLogRepository logRepository;
	
	private static String mLogContentFormat = "在{0}进行了{1}记录";

	@Override
	public AuditingBase get(Long id) {
		if (id == null) {
			return null;
		}
		return dataAccessor.get(AuditingBase.class, id);
	}

	@Override
	public void saveAuditing(AuditingBase auditing, String currentAuditType) {
		if (StringUtils.equals(currentAuditType,
				AuditType.audit_organization.toString())) {
			saveOrganizationAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_job_specification.toString())) {
			saveJobSpecificationAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_contract_version.toString())) {
			saveContractVersionAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_invite_apply.toString())) { // added by henry
															// ---->for add the
															// invite apply flow
			saveInviteApplyAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_contract_sign.toString())) {
			saveContractSignAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_transaction_organization.toString())
				|| StringUtils.equals(currentAuditType,
						AuditType.audit_transaction_other.toString())) {
			saveTransactionAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_financial_report_form.toString())) {
			saveFinancialReportFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_financial_payment_apply_form.toString())) {
			saveFinancialPaymentApplyFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_financial_in_bill_form.toString())) {
			saveFinancialInBillFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_administration_evection_apply_form.toString())) {
			saveAdministrationEvectionApplyFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_administration_evection_report_form.toString())) {
			saveAdministrationEvectionReportFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_administration_evection_cost_report_form
						.toString())) {
			saveAdministrationEvectionCostApplyFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_administration_out_apply_form.toString())) {
			saveAdministrationOutApplyFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_administration_leave_apply_form.toString())) {
			saveAdministrationLeaveApplyFormAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_train_plan.toString())) { // 培训计划
			saveTrainPlanAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_train_plan_outing.toString())) { // 培训计划
			saveTrainPlanAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_train_outing_plan_close.toString())) { // 外训结案
			saveTrainPlanCloseAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_leave_office.toString())) { // 离职申请
			saveLeaveOfficeApplyAudit(auditing);
		} else if (StringUtils.equals(currentAuditType,
				AuditType.audit_exam_qual_target.toString())) { // 定性考核
			saveQualScoreApplyAudit(auditing);
		}else if (StringUtils.equals(currentAuditType,
				AuditType.audit_exam_award.toString())) { // 奖罚审核
			saveAwardAudit(auditing);
		}
	}

	private void saveOrganizationAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		OrganizationAuditing a = dataAccessor.get(OrganizationAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.organization, a
				.getOrganization().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getOrganization(),
					a.getAuditNo() + 1);
		} else {
			Organization organization = a.getOrganization();
			organization.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(organization);

			// 给下一个审核结点发消息
			sendOrganizationMessageToNextAuditNode(a);
		}
	}

	private void saveJobSpecificationAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		JobSpecificationAuditing a = dataAccessor.get(
				JobSpecificationAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.job_specification, a
				.getJobSpecification().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getJobSpecification(),
					a.getAuditNo() + 1);
		} else {
			JobSpecification jobSpecification = a.getJobSpecification();
			jobSpecification.setAuditStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(jobSpecification);

			// 给下一个审核结点发消息
			sendJobSpecificationMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存合同版本审核对象
	 * 
	 * @param auditing
	 */
	private void saveContractVersionAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		ContractVersionAuditing a = dataAccessor.get(
				ContractVersionAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.contract_version, a
				.getContractVersion().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getContractVersion(),
					a.getAuditNo() + 1);
		} else {
			ContractVersion contractVersion = a.getContractVersion();
			contractVersion.setAuditStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(contractVersion);

			// 给下一个审核结点发消息
			sendContractVersionMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存合同签订审核对象
	 * 
	 * @param auditing
	 */
	private void saveContractSignAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		ContractSignAuditing a = dataAccessor.get(ContractSignAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		ContractSign sign = a.getContractSign();
		ContractSignZz signZz = a.getContractSignZz();
		// 审核结点状态改变后，清除本审核结点对象对应的消息
		if (sign != null) {
			auditingRepository.deleteMessage(MessageType.contract_sign,
					sign.getId());

			// 如果未通过审核,则再创建一个审核流程
			if (isReject) {
				auditingRepository
						.saveAuditingProcess(sign, a.getAuditNo() + 1);
			} else {
				if (a.isLast()) {
					sign.setState(3);
					sign.setAuditStatus(AuditStatus.pass_audit);
					dataAccessor.save(sign);
				} else {
					if (sign.getState() == null || sign.getState() != 2) {
						sign.setState(2);
						dataAccessor.save(sign);
					}
					// 给下一个审核结点发消息
					sendContractSignMessageToNextAuditNode(a);
				}
			}
		}
		if (signZz != null) {
			auditingRepository.deleteMessage(MessageType.contract_sign,
					signZz.getId());

			// 如果未通过审核,则再创建一个审核流程
			if (isReject) {
				auditingRepository.saveAuditingProcess(signZz,
						a.getAuditNo() + 1);
			} else {
				if (a.isLast()) {
					signZz.setState(3);
					signZz.setAuditStatus(AuditStatus.pass_audit);
					dataAccessor.save(signZz);
				} else {
					if (signZz.getState() == null || signZz.getState() != 2) {
						signZz.setState(2);
						dataAccessor.save(signZz);
					}
					// 给下一个审核结点发消息
					sendContractSignMessageToNextAuditNode(a);
				}
			}
		}
	}

	/**
	 * 保存招聘审核对象
	 * 
	 * @param auditing
	 */
	private void saveInviteApplyAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		InviteApplyAuditing a = dataAccessor.get(InviteApplyAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getInviteApply(),
					a.getAuditNo() + 1);
		} else {
			InviteApply inviteApply = a.getInviteApply();
			inviteApply.setAuditStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(inviteApply);
		}
	}

	/**
	 * 保存异动审核对象
	 * 
	 * @param auditing
	 */
	private void saveTransactionAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		TransactionAuditing a = dataAccessor.get(TransactionAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getTransaction(),
					a.getAuditNo() + 1);
		} else {
			Transaction transaction = a.getTransaction();
			transaction.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(transaction);
		}
	}

	/**
	 * 保存现金报支单审核对象
	 * 
	 * @param auditing
	 */
	private void saveFinancialReportFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		FinancialReportFormAuditing a = dataAccessor.get(
				FinancialReportFormAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.financial_report_form, a
				.getFinancialReportForm().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getFinancialReportForm(),
					a.getAuditNo() + 1);
		} else {
			FinancialReportForm form = a.getFinancialReportForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendFinancialReportFormMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存用款申请单审核对象
	 * 
	 * @param auditing
	 */
	private void saveFinancialPaymentApplyFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		FinancialPaymentApplyFormAuditing a = dataAccessor.get(
				FinancialPaymentApplyFormAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(
				MessageType.financial_payment_apply_form, a.getApplyForm()
						.getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getApplyForm(),
					a.getAuditNo() + 1);
		} else {
			FinancialPaymentApplyForm form = a.getApplyForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendFinancialPaymentApplyFormMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存入帐单审核对象
	 * 
	 * @param auditing
	 */
	private void saveFinancialInBillFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		FinancialInBillFormAuditing a = dataAccessor.get(
				FinancialInBillFormAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.financial_in_bill_form, a
				.getFinancialInBillForm().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getFinancialInBillForm(),
					a.getAuditNo() + 1);
		} else {
			FinancialInBillForm form = a.getFinancialInBillForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendFinancialInBillFormMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存出差申请单审核对象
	 * 
	 * @param auditing
	 */
	private void saveAdministrationEvectionApplyFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		AdministrationEvectionApplyFormAuditing a = dataAccessor
				.get(AdministrationEvectionApplyFormAuditing.class,
						auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(
				MessageType.administration_evection_apply_form, a.getForm()
						.getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getForm(),
					a.getAuditNo() + 1);
		} else {
			AdministrationEvectionApplyForm form = a.getForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendAdministrationEvectionApplyFormMessageToNextAuditNode(a);

            if(a.isLast()){//最后一个审核通过，将出差数据插入到手勤系统表中
                try {
                    checkQingJiaService();
                    QingJia qingJia = buildQingJia(form.getWork().getBaseId().getId().intValue(), "00101", form.getEvectionStartDate(), form.getEvectionEndDate(), form.getEvectionReason());
                    int row = qingJiaService.insert(qingJia);
                    System.out.println("insert evection data : "+row);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
		}
	}

	/**
	 * 保存出差报告单审核对象
	 * 
	 * @param auditing
	 */
	private void saveAdministrationEvectionReportFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		AdministrationEvectionReportFormAuditing a = dataAccessor.get(
				AdministrationEvectionReportFormAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(
				MessageType.administration_evection_report_form, a.getForm()
						.getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getForm(),
					a.getAuditNo() + 1);
		} else {
			AdministrationEvectionReportForm form = a.getForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendAdministrationEvectionReportFormMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存出差旅申请单审核对象
	 * 
	 * @param auditing
	 */
	private void saveAdministrationEvectionCostApplyFormAudit(
			AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		AdministrationEvectionCostApplyFormAuditing a = dataAccessor.get(
				AdministrationEvectionCostApplyFormAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(
				MessageType.administration_evection_cost_report_form, a
						.getForm().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getForm(),
					a.getAuditNo() + 1);
		} else {
			AdministrationEvectionCostApplyForm form = a.getForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendAdministrationEvectionCostApplyFormMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存外出申请单审核对象
	 * 
	 * @param auditing
	 */
	private void saveAdministrationOutApplyFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		AdministrationOutApplyFormAuditing a = dataAccessor.get(
				AdministrationOutApplyFormAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(
				MessageType.administration_out_apply_form, a.getForm().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getForm(),
					a.getAuditNo() + 1);
		} else {
			AdministrationOutApplyForm form = a.getForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendAdministrationOutApplyFormMessageToNextAuditNode(a);

            if(a.isLast()){//最后一个审核通过，将出差数据插入到手勤系统表中
                try {
                    checkQingJiaService();
                    QingJia qingJia = buildQingJia(form.getWork().getBaseId().getId().intValue(), "00109", form.getStartDate(), form.getEndDate(), form.getEvectionReason());
                    int row = qingJiaService.insert(qingJia);
                    System.out.println("insert evection data : "+row);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
		}
	}

	/**
	 * 保存请假申请单审核对象
	 */
	private void saveAdministrationLeaveApplyFormAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

        AdministrationLeaveApplyFormAuditing a = dataAccessor.get(AdministrationLeaveApplyFormAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.administration_leave_apply_form, a.getForm().getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getForm(), a.getAuditNo() + 1);
		} else {
			AdministrationLeaveApplyForm form = a.getForm();
			form.setStatus(a.isLast() ? AuditStatus.pass_audit : AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendAdministrationLeaveApplyFormMessageToNextAuditNode(a);

            if(a.isLast()){//最后一个审核通过，将出差数据插入到手勤系统表中
                try {
                    checkQingJiaService();
                    QingJia qingJia = buildQingJia(form.getWork().getBaseId().getId().intValue(), form.getTypeCode(), form.getStartDate(), form.getEndDate(), form.getReason());
                    int row = qingJiaService.insert(qingJia);
                    System.out.println("insert evection data : "+row);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
		}
	}

	/**
	 * 保存培训计划审核流程
	 * 
	 * @param auditing
	 */
	private void saveTrainPlanAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		TrainPlanAuditing a = dataAccessor.get(TrainPlanAuditing.class,
				auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getTrainPlan(),
					a.getAuditNo() + 1);
		} else {
			TrainPlan form = a.getTrainPlan();
			form.setAuditStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个审核结点发消息
			sendTrainPlanMessageToNextAuditNode(a);
		}

		SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:ss");
		// 培训审核结束后给所有人和教师发消息
		if (auditing.isLast() && auditing.getStatus() == AuditStatus.pass_audit
				&& a.getTrainPlan() != null) {
			LimitedList<EmployeeinfoWork> employeeinfoWorks = trainPlanRepository
					.getTrainPlanEmployeeinfoWorkTargets(a.getTrainPlan()
							.getId(), a.getTrainPlan().getLecturerType(), null,
							null);

			String url = "";
			if (a.getTrainPlan().getLecturerType() == 0) {
				url = String.format(
						"train/assess_list.xhtml?organizationId=%s", a
								.getTrainPlan().getOrganization().getId()
								.longValue());
			} else {
				url = String.format(
						"train/assess_outing_list.xhtml?organizationId=%s", a
								.getTrainPlan().getOrganization().getId()
								.longValue());
			}
			try {
				if (employeeinfoWorks != null && employeeinfoWorks.size() > 0) {
					Iterator<EmployeeinfoWork> it = employeeinfoWorks
							.iterator();
					while (it.hasNext()) {
						EmployeeinfoWork work = it.next();
						String[] data = { a.getTrainPlan().getTitle(),
								sf.format(a.getTrainPlan().getPlanStartDate()) };
						auditingRepository.saveMessage(
								MessageType.train_plan_notify, url, a
										.getTrainPlan().getId(),
								work.getDuty(), work, data);
						
						//添加培训日志
						saveEmployeeinfoLog(work, EmployeeinfoTypeEnum.train, 
								a.getAuditing().getEmployee() != null ? a.getAuditing().getEmployee().getName() : "", 
										a.getAuditing().getEmployee() != null ? a.getAuditing().getId() : 0L);
					}
				}

				// 发送给培训老师
				if (a.getTrainPlan().getLecturerType() == 0
						&& a.getTrainPlan().getTrainLecturer() != null) {
					EmployeeinfoWork work = a.getTrainPlan().getTrainLecturer()
							.getEmployeeinfoWork();
					String[] data = { a.getTrainPlan().getTitle(),
							sf.format(a.getTrainPlan().getPlanStartDate()) };
					auditingRepository.saveMessage(
							MessageType.train_plan_notify, url, a
									.getTrainPlan().getId(), work.getDuty(),
							work, data);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 保存外训结案审核流程
	 * 
	 * @param auditing
	 */
	private void saveTrainPlanCloseAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		TrainOutingPlanCloseAuditing a = dataAccessor.get(
				TrainOutingPlanCloseAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getTrainPlan(),
					a.getAuditNo() + 1);
		} else {
			TrainPlan form = a.getTrainPlan();
			form.setCloseAuditStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个发送消息
			sendTrainPlanCloseMessageToNextAuditNode(a);
		}
	}

	/**
	 * 保存离职申请审核对象
	 * 
	 * @param auditing
	 */
	private void saveLeaveOfficeApplyAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		LeaveOfficeApplyAuditing a = dataAccessor.get(
				LeaveOfficeApplyAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		// 审核结点状态改变后，清除本审核结点对象对应的消息
		auditingRepository.deleteMessage(MessageType.leave_office, a.getApply()
				.getId());

		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getApply(),
					a.getAuditNo() + 1);
		} else {
			LeaveOfficeApply apply = a.getApply();
			apply.setStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(apply);

			// 给下一个审核结点发消息
			sendLeaveOfficeApplyMessageToNextAuditNode(a);
			
			// added by henry for the log add @{
			if(a.isLast()){	
				saveEmployeeinfoLog(a.getApply().getWork(), EmployeeinfoTypeEnum.resignation, 
						a.getAuditing().getEmployee() != null ? a.getAuditing().getEmployee().getName() : "", 
								a.getAuditing().getEmployee() != null ? a.getAuditing().getId() : 0L);
			}
			//@}
		}
	}

	/** 保存定性考核　 */
	private void saveQualScoreApplyAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		ExamQualTargetAuditing a = dataAccessor.get(
				ExamQualTargetAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);

		if (auditing.getStatus() == AuditStatus.within_audit) {
			// 给下一个审核结点发消息
			sendQualScoreMessageToNextAuditNode(a);
		}
	}
	
	/** 保存定性考核　 */
	private void saveAwardAudit(AuditingBase auditing) {
		boolean isReject = auditing.getStatus() == AuditStatus.reject_audit;

		ExamAwardAuditing a = dataAccessor.get(
				ExamAwardAuditing.class, auditing.getId());
		a.setStatus(auditing.getStatus());
		a.setAuditContent(auditing.getAuditContent());
		dataAccessor.save(a);
		
		// 如果未通过审核,则再创建一个审核流程
		if (isReject) {
			auditingRepository.saveAuditingProcess(a.getExamAward(),
					a.getAuditNo() + 1);
		} else {
			ExamAward form = a.getExamAward();
			form.setAuditStatus(a.isLast() ? AuditStatus.pass_audit
					: AuditStatus.within_audit);
			dataAccessor.save(form);

			// 给下一个发送消息
			sendAwardMessageToNextAuditNode(a);
		}
	}

	// 给下一个组织架构审核结点发消息
	public void sendOrganizationMessageToNextAuditNode(
			OrganizationAuditing currentAuditNode) {
		final Organization organization = currentAuditNode.getOrganization();
		// 查找下一个审核结点
		List<OrganizationAuditing> auditProcess = dataAccessor
				.findByHql(
						OrganizationAuditing.class,
						"from OrganizationAuditing a where a.organization=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { organization,
								currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			OrganizationAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendOrganizationMessage(
					currentAuditNode.getOrganization(),
					nextAuditNode.getAuditing());
		}
	}

	// 给下一个工作说明书审核结点发消息
	public void sendJobSpecificationMessageToNextAuditNode(
			JobSpecificationAuditing currentAuditNode) {
		final JobSpecification jobSpecification = currentAuditNode
				.getJobSpecification();

		// 查找下一个审核结点
		List<JobSpecificationAuditing> auditProcess = dataAccessor
				.findByHql(
						JobSpecificationAuditing.class,
						"from JobSpecificationAuditing a where a.jobSpecification=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { jobSpecification,
								currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			JobSpecificationAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendJobSpecificationMessage(
					currentAuditNode.getJobSpecification(),
					nextAuditNode.getAuditing());
		}
	}

	// 给下一个合同版本审核结点发消息
	public void sendContractVersionMessageToNextAuditNode(
			ContractVersionAuditing currentAuditNode) {
		final ContractVersion contractVersion = currentAuditNode
				.getContractVersion();

		// 查找下一个审核结点
		List<ContractVersionAuditing> auditProcess = dataAccessor
				.findByHql(
						ContractVersionAuditing.class,
						"from ContractVersionAuditing a where a.contractVersion=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { contractVersion,
								currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			ContractVersionAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendContractVersionMessage(nextAuditNode);
		}
	}

	// 给下一个合同签订审核结点发消息
	public void sendContractSignMessageToNextAuditNode(
			ContractSignAuditing currentAuditNode) {
		final ContractSign contractSign = currentAuditNode.getContractSign();

		// 查找下一个审核结点
		List<ContractSignAuditing> auditProcess = dataAccessor
				.findByHql(
						ContractSignAuditing.class,
						"from ContractSignAuditing a where a.contractSign=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { contractSign,
								currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			ContractSignAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendContractSignMessage(nextAuditNode);
		}
	}

	// 给下一个现金报支单审核结点发消息
	public void sendFinancialReportFormMessageToNextAuditNode(
			FinancialReportFormAuditing currentAuditNode) {
		final FinancialReportForm form = currentAuditNode
				.getFinancialReportForm();

		// 查找下一个审核结点
		List<FinancialReportFormAuditing> auditProcess = dataAccessor
				.findByHql(
						FinancialReportFormAuditing.class,
						"from FinancialReportFormAuditing a where a.financialReportForm=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			FinancialReportFormAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendFinancialReportFormMessage(nextAuditNode);
		}
	}

	// 给下一个用款申请单审核结点发消息
	public void sendFinancialPaymentApplyFormMessageToNextAuditNode(
			FinancialPaymentApplyFormAuditing currentAuditNode) {
		final FinancialPaymentApplyForm form = currentAuditNode.getApplyForm();

		// 查找下一个审核结点
		List<FinancialPaymentApplyFormAuditing> auditProcess = dataAccessor
				.findByHql(
						FinancialPaymentApplyFormAuditing.class,
						"from FinancialPaymentApplyFormAuditing a where a.applyForm=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			FinancialPaymentApplyFormAuditing nextAuditNode = auditProcess
					.get(0);
			auditingRepository
					.sendFinancialPaymentApplyFormMessage(nextAuditNode);
		}
	}

	// 给下一个入帐单审核结点发消息
	public void sendFinancialInBillFormMessageToNextAuditNode(
			FinancialInBillFormAuditing currentAuditNode) {
		final FinancialInBillForm form = currentAuditNode
				.getFinancialInBillForm();

		// 查找下一个审核结点
		List<FinancialInBillFormAuditing> auditProcess = dataAccessor
				.findByHql(
						FinancialInBillFormAuditing.class,
						"from FinancialInBillFormAuditing a where a.financialInBillForm=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			FinancialInBillFormAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendFinancialInBillFormMessage(nextAuditNode);
		}
	}

	// 给下一个出差申请单审核结点发消息
	public void sendAdministrationEvectionApplyFormMessageToNextAuditNode(
			AdministrationEvectionApplyFormAuditing currentAuditNode) {
		final AdministrationEvectionApplyForm form = currentAuditNode.getForm();

		// 查找下一个审核结点
		List<AdministrationEvectionApplyFormAuditing> auditProcess = dataAccessor
				.findByHql(
						AdministrationEvectionApplyFormAuditing.class,
						"from AdministrationEvectionApplyFormAuditing a where a.form=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			AdministrationEvectionApplyFormAuditing nextAuditNode = auditProcess
					.get(0);
			auditingRepository
					.sendAdministrationEvectionApplyFormMessage(nextAuditNode);
		}
	}

	// 给下一个出差报告单审核结点发消息
	public void sendAdministrationEvectionReportFormMessageToNextAuditNode(
			AdministrationEvectionReportFormAuditing currentAuditNode) {
		final AdministrationEvectionReportForm form = currentAuditNode
				.getForm();

		// 查找下一个审核结点
		List<AdministrationEvectionReportFormAuditing> auditProcess = dataAccessor
				.findByHql(
						AdministrationEvectionReportFormAuditing.class,
						"from AdministrationEvectionReportFormAuditing a where a.form=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			AdministrationEvectionReportFormAuditing nextAuditNode = auditProcess
					.get(0);
			auditingRepository
					.sendAdministrationEvectionReportFormMessage(nextAuditNode);
		}
	}

	// 给下一个出差费用申报单审核结点发消息
	public void sendAdministrationEvectionCostApplyFormMessageToNextAuditNode(
			AdministrationEvectionCostApplyFormAuditing currentAuditNode) {
		final AdministrationEvectionCostApplyForm form = currentAuditNode
				.getForm();

		// 查找下一个审核结点
		List<AdministrationEvectionCostApplyFormAuditing> auditProcess = dataAccessor
				.findByHql(
						AdministrationEvectionCostApplyFormAuditing.class,
						"from AdministrationEvectionCostApplyFormAuditing a where a.form=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			AdministrationEvectionCostApplyFormAuditing nextAuditNode = auditProcess
					.get(0);
			auditingRepository
					.sendAdministrationEvectionCostApplyFormMessage(nextAuditNode);
		}
	}

	// 给下一个外出申报单审核结点发消息
	public void sendAdministrationOutApplyFormMessageToNextAuditNode(
			AdministrationOutApplyFormAuditing currentAuditNode) {
		final AdministrationOutApplyForm form = currentAuditNode.getForm();

		// 查找下一个审核结点
		List<AdministrationOutApplyFormAuditing> auditProcess = dataAccessor
				.findByHql(
						AdministrationOutApplyFormAuditing.class,
						"from AdministrationOutApplyFormAuditing a where a.form=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			AdministrationOutApplyFormAuditing nextAuditNode = auditProcess
					.get(0);
			auditingRepository
					.sendAdministrationOutApplyFormMessage(nextAuditNode);
		}
	}

	// 给下一个请假申报单审核结点发消息
	public void sendAdministrationLeaveApplyFormMessageToNextAuditNode(AdministrationLeaveApplyFormAuditing currentAuditNode) {
		final AdministrationLeaveApplyForm form = currentAuditNode.getForm();

		// 查找下一个审核结点
		List<AdministrationLeaveApplyFormAuditing> auditProcess = dataAccessor
				.findByHql(AdministrationLeaveApplyFormAuditing.class,
						"from AdministrationLeaveApplyFormAuditing a where a.form=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { form, currentAuditNode.getAuditNo(), AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
            AdministrationLeaveApplyFormAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendAdministrationLeaveApplyFormMessage(nextAuditNode);
		}
	}

	// 给下一个离职审核结点发消息
	public void sendLeaveOfficeApplyMessageToNextAuditNode(
			LeaveOfficeApplyAuditing currentAuditNode) {
		final LeaveOfficeApply apply = currentAuditNode.getApply();

		// 查找下一个审核结点
		List<LeaveOfficeApplyAuditing> auditProcess = dataAccessor
				.findByHql(
						LeaveOfficeApplyAuditing.class,
						"from LeaveOfficeApplyAuditing a where a.apply=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { apply, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			LeaveOfficeApplyAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendLeaveOfficeApplyMessage(nextAuditNode);
		}
	}

	// 给下一个定性考核人员结点发消息
	public void sendQualScoreMessageToNextAuditNode(
			ExamQualTargetAuditing currentAuditNode) {
		final ExamQualScore score = currentAuditNode.getExamQualScore();

		// 查找下一个审核结点
		List<ExamQualTargetAuditing> auditProcess = dataAccessor
				.findByHql(
						ExamQualTargetAuditing.class,
						"from ExamQualTargetAuditing a where a.examQualScore=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { score, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			ExamQualTargetAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendQualScoreMessage(nextAuditNode);
		}
	}

	// 给下一个培训计划审核结点发消息
	public void sendTrainPlanMessageToNextAuditNode(
			TrainPlanAuditing currentAuditNode) {
		final TrainPlan plan = currentAuditNode.getTrainPlan();

		// 查找下一个审核结点
		List<TrainPlanAuditing> auditProcess = dataAccessor
				.findByHql(
						TrainPlanAuditing.class,
						"from TrainPlanAuditing a where a.trainPlan=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { plan, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			TrainPlanAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendTrainPlanMessage(nextAuditNode);
		}
	}

	// 给下一个培训计划审核结点发消息
	public void sendTrainPlanCloseMessageToNextAuditNode(
			TrainOutingPlanCloseAuditing currentAuditNode) {
		final TrainPlan plan = currentAuditNode.getTrainPlan();

		// 查找下一个审核结点
		List<TrainOutingPlanCloseAuditing> auditProcess = dataAccessor
				.findByHql(
						TrainOutingPlanCloseAuditing.class,
						"from TrainOutingPlanCloseAuditing a where a.trainPlan=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { plan, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			TrainOutingPlanCloseAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendTrainPlanCloseMessage(nextAuditNode);
		}
	}
	
	// 给下一个奖罚审核结点发消息
	public void sendAwardMessageToNextAuditNode(
			ExamAwardAuditing currentAuditNode) {
		final ExamAward award = currentAuditNode.getExamAward();

		// 查找下一个审核结点
		List<ExamAwardAuditing> auditProcess = dataAccessor
				.findByHql(
						ExamAwardAuditing.class,
						"from ExamAwardAuditing a where a.examAward=? and a.auditNo=? and a.status=? order by a.id asc",
						new Object[] { award, currentAuditNode.getAuditNo(),
								AuditStatus.wait_audit }, new Limit(0, 1), null);
		if (auditProcess != null && !auditProcess.isEmpty()) {
			ExamAwardAuditing nextAuditNode = auditProcess.get(0);
			auditingRepository.sendAwardMessage(nextAuditNode);
		}
	}
	
	/**
	 * 保存员工记录日志
	 * @param work
	 * @param employeeinfoTypeEnum
	 * @param author
	 * @param authorId
	 */
	private void saveEmployeeinfoLog(EmployeeinfoWork work,EmployeeinfoTypeEnum employeeinfoTypeEnum,String author,Long authorId){
		EmployeeinfoLog employeeinfoLog = new EmployeeinfoLog();
		employeeinfoLog.setEmployeeinfoTypeEnum(employeeinfoTypeEnum);
		employeeinfoLog.setEmployeeinfoWork(work);
		employeeinfoLog.setContent(MessageFormat.format(mLogContentFormat, 
				new SimpleDateFormat("yyyy-MM-dd HH:mm").format(new Date(System.currentTimeMillis())) , employeeinfoTypeEnum.getName()));
		try {
			employeeinfoLog.setAuthor(author);
			employeeinfoLog.setAuthorId(authorId);
			logRepository.saveEmployeeinfoLog(employeeinfoLog);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

    //=============================================================
    //同步出差和外出数据到考勤系统
    private QingJiaService qingJiaService;
    private void checkQingJiaService()throws Exception{
        if(qingJiaService == null){
            qingJiaService = new QingJiaService();
            qingJiaService.connection();
        }
    }

    private QingJia buildQingJia(int userId, String type, Date startDate, Date endDate, String reason){
        QingJia qingJia = new QingJia();
        qingJia.setUser_serial(userId);
        qingJia.setBh(type); //出差"00101",  外出：00109
        qingJia.setKssj(startDate);
        qingJia.setJssj(endDate);
        qingJia.setBz(reason);
        return qingJia;
    }
}
